package cate.game.pvp.eliterace.util;

import cate.game.event.eliterace.EliteRaceTimerEvent.FinalEvent;
import cate.game.event.eliterace.EliteRaceTimerEvent.KoEvent;
import cate.game.event.eliterace.EliteRaceTimerEvent.TrialEvent;
import cate.game.pvp.eliterace.data.EliteRaceSpec;
import cate.game.pvp.eliterace.timer.EliteRaceTimerTask.Settings;
import lombok.Data;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.StringUtils;

import java.util.Objects;

import static cate.game.event.eliterace.EliteRaceTimerEvent.EventType.FINAL;
import static cate.game.event.eliterace.EliteRaceTimerEvent.EventType.KO;
import static cate.game.event.eliterace.EliteRaceTimerEvent.EventType.TRIAL;

public final class EliteRaceSpecUtils {

    public static int getVideoLevel(EliteRaceSpec spec) {
        switch (spec.getPeriod()) {
            case 1:
                return spec.getRound();
            case 2:
                return 6 + spec.getRound();
            case 3:
                return 9 + spec.getRound();
        }
        throw new IllegalStateException("不应该运行到这里!");
    }

    public static boolean isTrial(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 1;
    }

    /**
     * 解析阶段消息1-1-1-1-1格式
     * @param key
     * @return
     */
    public static EliteRaceSpec deserialize(String key) {
        if (!StringUtils.hasLength(key)) {
            return null;
        }

        String[] splitArray = key.split("-");
        if (ArrayUtils.isEmpty(splitArray)) {
            return null;
        }

        if (splitArray.length < 5) {
            return null;
        }


        return EliteRaceSpec.of(
                Byte.parseByte(splitArray[0]),
                Byte.parseByte(splitArray[1]),
                Byte.parseByte(splitArray[2]),
                Byte.parseByte(splitArray[3]),
                Byte.parseByte(splitArray[4])
        );
    }

    @Data
    public static class SpecPair {
        private EliteRaceSpec from;
        private EliteRaceSpec to;

        public static SpecPair of(EliteRaceSpec from, EliteRaceSpec to) {
            SpecPair pair = new SpecPair();
            pair.setFrom(from);
            pair.setTo(to);
            return pair;
        }
    }

    public static SpecPair checkQuerySpec(
            EliteRaceSpec from,
            EliteRaceSpec to,
            EliteRaceSpec spec) {

        if (Objects.nonNull(from) && Objects.nonNull(to)
                && Objects.compare(to, from, EliteRaceSpec::compareTo) < 0) {
            return null;
        }

        EliteRaceSpec sTo = to;
        if (Objects.compare(spec, to, EliteRaceSpec::compareTo) < 0) {
            sTo = spec.getStep() >= (byte) 2
                    ? EliteRaceSpec.of(
                    spec.getSeason(),
                    spec.getPeriod(),
                    spec.getGroup(),
                    spec.getRound(),
                    spec.getStep())
                    : EliteRaceSpec.of(
                    spec.getSeason(),
                    spec.getPeriod(),
                    spec.getGroup(),
                    (byte) (spec.getRound() - 1),
                    (byte) 3);
        }
        return SpecPair.of(from, sTo);
    }

    public static boolean isReadyStep(EliteRaceSpec spec) {
        return isTrialReadyStep(spec)
                || isKoReadyStep(spec)
                || isFinalReadyStep(spec);
    }

    public static boolean isTrialReadyStep(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 1 && spec.getStep() == (byte) 3;
    }

    public static boolean isKoReadyStep(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 2 && spec.getStep() == (byte) 3;
    }

    public static boolean isFinalReadyStep(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 3 && spec.getStep() == (byte) 3;
    }


    public static boolean isBetRwd(EliteRaceSpec spec) {
        return isTrialBetRwd(spec)
                || isKoBetRwd(spec)
                || isFinalBetRwd(spec);
    }

    public static boolean isTrialBetRwd(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 1 && spec.getStep() == (byte) 3;
    }

    public static boolean isKoBetRwd(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 2 && spec.getStep() == (byte) 3;
    }

    public static boolean isFinalBetRwd(EliteRaceSpec spec) {
        return spec.getPeriod() == (byte) 3 && spec.getStep() == (byte) 3;
    }

    public static int getTrialFlag(EliteRaceSpec spec) {
        return getStepFlag(TRIAL.getFlag(), spec);
    }

    public static int getTrialFlag(Settings settings) {
        return getTrialFlag(settings.getSpec());
    }

    public static int getTrialFlag(TrialEvent trialEvent) {
        return getTrialFlag(trialEvent.getSpec());
    }

    public static int getKoFlag(EliteRaceSpec spec) {
        return getStepFlag(KO.getFlag(), spec);
    }

    public static int getKoFlag(Settings settings) {
        return getKoFlag(settings.getSpec());
    }

    public static int getKoFlag(KoEvent koEvent) {
        return getKoFlag(koEvent.getSpec());
    }

    public static int getFinalFlag(EliteRaceSpec spec) {
        return getStepFlag(FINAL.getFlag(), spec);
    }

    public static int getFinalFlag(Settings settings) {
        return getFinalFlag(settings.getSpec());
    }

    public static int getFinalFlag(FinalEvent finalEvent) {
        return getFinalFlag(finalEvent.getSpec());
    }

    public static int getStepFlag(int eventMainFlag, EliteRaceSpec spec) {
        return eventMainFlag + (spec.getRound() - 1) * 3 + spec.getStep();
    }

    public static boolean isMatchTrialSimulator(Settings settings) {
        return settings.getEventType() == TRIAL
                && settings.getSpec().getStep() == (byte) 1;
    }

    public static boolean isMatchKoSimulator(Settings settings) {
        return settings.getEventType() == KO
                && settings.getSpec().getStep() == (byte) 1;
    }

    public static boolean isMatchFinalSimulator(Settings settings) {
        return settings.getEventType() == FINAL
                && settings.getSpec().getStep() == (byte) 1;
    }

    public static boolean isMatchBetRwdSimulator(Settings settings) {
        return isMatchTrialBetRwdSimulator(settings)
                || isMatchKoBetRwdSimulator(settings)
                || isMatchFinalBetRwdSimulator(settings);
    }

    public static boolean isMatchTrialBetRwdSimulator(Settings settings) {
        return settings.getEventType() == TRIAL
                && settings.getSpec().getStep() == (byte) 2;
    }

    public static boolean isMatchKoBetRwdSimulator(Settings settings) {
        return settings.getEventType() == KO
                && settings.getSpec().getStep() == (byte) 2;
    }

    public static boolean isMatchFinalBetRwdSimulator(Settings settings) {
        return settings.getEventType() == FINAL
                && settings.getSpec().getStep() == (byte) 2;
    }

    public static boolean isMatchReadySimulator(Settings settings) {
        return isMatchTrialReadySimulator(settings)
                || isMatchKoReadySimulator(settings)
                || isMatchFinalReadySimulator(settings);
    }

    public static boolean isMatchTrialReadySimulator(Settings settings) {
        return settings.getEventType() == TRIAL
                && settings.getSpec().getStep() == (byte) 3;
    }

    public static boolean isMatchKoReadySimulator(Settings settings) {
        return settings.getEventType() == KO
                && settings.getSpec().getStep() == (byte) 3;
    }

    public static boolean isMatchFinalReadySimulator(Settings settings) {
        return settings.getEventType() == FINAL
                && settings.getSpec().getStep() == (byte) 3;
    }

    private EliteRaceSpecUtils() {
    }
}
